﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Jewelnoid
{
    class AnimatedObject : Object2D
    {
        public struct AnimationStructure
        {
            public int frameWidth;
            public int frameHeight;
            public int frameCount;
            public int framePerSecond;
            public int X;
            public int Y;
        }

        public Dictionary<String, AnimationStructure> animationsList;

        public AnimationStructure animation;

        public Rectangle sourceRect;
        public int currentFrame;

        private double secondsCount;
        private String defaultName;

        public AnimatedObject(Texture2D texture, Vector2 position, Color color, Vector2 spriteSize, int framePerSecond)
            : base(texture, position, color)
        {
            this.animationsList = new Dictionary<string, AnimationStructure>();
            this.sourceRect = new Rectangle(0, 0, (int)spriteSize.X, (int)spriteSize.Y);
            this.defaultName = "default";

            AnimationStructure animationDefault = new AnimationStructure();
            animationDefault.frameCount = texture.Width / (int)spriteSize.X;
            animationDefault.frameWidth = (int)spriteSize.X;
            animationDefault.frameHeight = (int)spriteSize.Y;
            animationDefault.framePerSecond = framePerSecond;
            animationDefault.X = 0;
            animationDefault.Y = 0;
            animationsList.Add(this.defaultName, animationDefault);

            changeAnimation(this.defaultName);

            this.currentFrame = 0;
            this.secondsCount = 0;

            this.position.X += this.texture.Width / 2 - this.sourceRect.Width / 2;
            this.position.Y += this.texture.Height / 2 - this.sourceRect.Height / 2;
        }

        public void changeAnimation(string name)
        {
            this.animation = this.animationsList[name];
        }

        /// <summary>
        ///     Add a animation with the default configuration.
        ///     To add a non-default animation, create a new AnimationStructure and add to the list manually.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="startPosition"></param>
        public void addAnimation(string name, Vector2 startPosition)
        {
            AnimationStructure newAnimation = new AnimationStructure();
            newAnimation.frameCount = this.texture.Width / this.animationsList[this.defaultName].frameWidth;
            newAnimation.frameWidth = this.animationsList[this.defaultName].frameWidth;
            newAnimation.frameHeight = this.animationsList[this.defaultName].frameHeight;
            newAnimation.framePerSecond = this.animationsList[this.defaultName].framePerSecond;
            newAnimation.X = (int)startPosition.X;
            newAnimation.Y = (int)startPosition.Y;

            this.animationsList.Add(name, newAnimation);
        }

        /// <summary>
        ///    This update run the animation until reach the last frame and stop.
        ///    To run a animation in loop, call the other update method.
        /// </summary>
        /// <param name="time"></param>
        public virtual void update(GameTime time)
        {
            updateRect();

            if (time.TotalGameTime.TotalSeconds - this.secondsCount > 1f / this.animation.framePerSecond)
            {
                this.secondsCount = time.TotalGameTime.TotalSeconds;

                if (this.currentFrame < this.animation.frameCount - 1)
                {
                    this.currentFrame++;
                }
            }
        }

        public void update(GameTime time, Boolean loop)
        {
            if (loop && this.currentFrame == this.animation.frameCount - 1)
            {
                this.currentFrame = 0;
            }
             
            update(time);
        }

        public override void updateRect()
        {
            this.sourceRect.X = this.currentFrame * this.animation.frameWidth;
            this.sourceRect.Y = this.animation.Y;

            this.rect.X = (int)this.position.X - this.texture.Width / 2;
            this.rect.Y = (int)this.position.Y - this.texture.Height / 2;

            this.rect.Width = this.sourceRect.Width = this.animation.frameWidth;
            this.rect.Height = this.sourceRect.Height = this.animation.frameHeight;
        }

        public override void draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(this.texture, this.position, this.sourceRect, this.color * alpha, this.rotation, this.pivot, this.scale, SpriteEffects.None, 0.5f);
            //spriteBatch.Draw(this.texture, this.rect, Color.Yellow);  //Desenha o retângulo de colisão.
        }
    }
}
